package com.yssoft.utils;


import com.yssoft.entity.core.ComparedResult;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;

import org.apache.commons.lang3.StringUtils;

/**
 * 对象比较工具类
 *
 * @author wmh
 * @date 2024-05-27 15:04:12
 */
public class CompareUtil {

    /**
     * 比较不同值，是否相等
     *
     * @param o1 值1
     * @param o2 值2
     * @return 比较结果，true相等，false不相等
     */
    public static boolean compareValues(Object o1, Object o2) {
        if (o1 == o2) {
            return true;
        }
        if (o1 == null && o2 == null) {
            return true;
        }
        if (o1 != null && o2 == null) {
            if (StringUtils.isBlank(String.valueOf(o1))) {
                return true;
            }
            return false;
        }
        if (o1 == null && o2 != null) {
            if (StringUtils.isBlank(String.valueOf(o2))) {
                return true;
            }
            return false;
        }


//        if(o1 == null || StringUtils.isBlank(String.valueOf(o1))){
//            if(o2 != null || StringUtils.isNotBlank(String.valueOf(o2))){
//                return false;
//            }
//            return true;
//        }
//        if(o1 != null && StringUtils.isNotBlank(String.valueOf(o1))){
//            if(o2 == null || StringUtils.isBlank(String.valueOf(o2))){
//                return false;
//            }else {
//                if(String.valueOf(o1).equals(String.valueOf(o2))){
//                    return true;
//                }else {
//                    return false;
//                }
//            }
//        }

//        if (o1 != null && o2 == null) {
//            return false;
//        }
//        if (o1 == null && o2 != null) {
//            return false;
//        }

        // BigDecimal比较用compareTo
        if (o1 instanceof BigDecimal && o2 instanceof BigDecimal) {
            BigDecimal decimal1 = new BigDecimal(String.valueOf(o1));
            BigDecimal decimal2 = new BigDecimal(String.valueOf(o2));
            // 0相等
            return decimal1.compareTo(decimal2) == 0;
        }

        if (o1 instanceof Timestamp) {
            o1 = new Date(((Timestamp) o1).getTime());
        }
        if (o2 instanceof Timestamp) {
            o2 = new Date(((Timestamp) o2).getTime());
        }

        return Objects.equals(o1, o2);
    }

    public static boolean objCheckNull(Object obj) {
        if (obj == null) {
            return true;
        }
        if (StringUtils.isBlank(String.valueOf(obj))) {
            return true;
        }
        if ("null".equals(String.valueOf(obj))) {
            return true;
        }
        return false;
    }

    /**
     * 对比两个对象修改值
     *
     * @param oldObject 旧对象
     * @param newObject 新对象
     * @return 对比结果列表
     */
    public static List<ComparedResult> compareTwoObject(Object oldObject, Object newObject) {
        // 为null时，不比较
        if (null == oldObject || null == newObject) {
            return Collections.emptyList();
        }

        // 不是同一个class
        if (oldObject.getClass() != newObject.getClass()) {
            throw new RuntimeException("不是同一个class！");
        }

        List<ComparedResult> comparedResultList = new ArrayList<>();
        Class<?> clazz = oldObject.getClass();

        // 获取所有字段
        Field[] Fields = clazz.getDeclaredFields();
        for (Field field : Fields) {
            try {

                // 获取注解
                CompareAnno compareAnno = field.getAnnotation(CompareAnno.class);
                // 没有注解，说明不对比字段，跳过
                if (null == compareAnno) {
                    continue;
                }

                String fieldKey = field.getName(); // 字段名
                String filedName = compareAnno.name(); // 字段中文名称
                String pattern = compareAnno.pattern(); // 格式

                // 前缀字段，存在（进行拼接，即：prefixField字段值 + name）
                String prefixField = compareAnno.prefixField();
                if (StringUtils.isNotBlank(prefixField)) {
                    filedName = getFieldValue(prefixField, oldObject) + filedName;
                }

                // 比较字段名
                String compareField = field.getName();
                if (StringUtils.isNotBlank(compareAnno.compareField())) {
                    compareField = compareAnno.compareField();
                }

                // 获取比较的属性值
                // 在oldObject上调用get方法等同于获得oldObject的属性值
                Object oldCompareValue = getFieldValue(compareField, oldObject);
                // 在newObject上调用get方法等同于获得newObject的属性值
                Object newCompareValue = getFieldValue(compareField, newObject);


                // 在oldObject上调用get方法等同于获得oldObject的属性值
                Object oldValue = getFieldValue(fieldKey, oldObject);
                // 在newObject上调用get方法等同于获得newObject的属性值
                Object newValue = getFieldValue(fieldKey, newObject);

                // 原来的值（字符串）
//                String oldContent = CastUtils.getFormatValue(oldValue, pattern);
                String oldContent = (String) getFormattedValue(oldValue, pattern.getClass());
                // 修改后的值（字符串）
//                String newContent = CastUtils.getFormatValue(newValue, pattern);
                String newContent = (String) getFormattedValue(newValue, pattern.getClass());

                // 对比两个值是否一致
                if (!compareValues(oldCompareValue, newCompareValue)) {
                    // 不一致
                    ComparedResult result = new ComparedResult();
                    result.setField(fieldKey);
                    result.setFieldName(filedName + "变更");
                    result.setOldValue(oldValue);
                    result.setNewValue(newValue);
                    result.setOldContent(oldContent);
                    result.setNewContent(newContent);
                    result.setPattern(pattern);
//                    result.setRemark(oldContent + " -> " + newContent);
                    result.setRemark("属性名：" + filedName + "  原值：" + (oldValue == null ? "空" : oldValue) + "  新值：" + (newValue == null ? "空" : newValue));
                    comparedResultList.add(result);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return comparedResultList;
    }

    /**
     * 对比两个对象修改值（检查是否为null）
     *
     * @param oldObject 旧对象
     * @param newObject 新对象
     * @return 对比结果列表
     */
    public static List<ComparedResult> compareTwoObjectCheckNull(Object oldObject, Object newObject) {
        // 都为null时，不比较
        if (null == oldObject && null == newObject) {
            return Collections.emptyList();
        }

        // 新增
        if (null == oldObject && null != newObject) {
            // 返回新增对比结果
            return addComparedResult(newObject);
        }

        // 删除
        if (null != oldObject && null == newObject) {
            // 返回删除对比结果
            return deleteComparedResult(oldObject);
        }

        // 都不为null时，对比两个对象修改值
        return compareTwoObject(oldObject, newObject);
    }

    /**
     * 新增对比结果
     *
     * @param obj 对象
     * @return 对比结果
     */
    public static List<ComparedResult> addComparedResult(Object obj) {
        List<ComparedResult> comparedResultList = new ArrayList<>();
        Class<?> clazz = obj.getClass();

//        String filedName = ""; // 字段中文名称
        String content = ""; // 内容

        // 获取类注解
//        CompareAnno compareAnno = clazz.getAnnotation(CompareAnno.class);
//        if (null != compareAnno) {
//            filedName = compareAnno.name();
//        }

        // 获取所有字段
        Field[] Fields = clazz.getDeclaredFields();
        for (Field field : Fields) {
            try {

                // 获取注解
                CompareAnno compareAnno = field.getAnnotation(CompareAnno.class);
                // 没有注解，说明不对比字段，跳过
                if (null == compareAnno) {
                    continue;
                }

                String fieldKey = field.getName(); // 字段名
                String filedName = compareAnno.name(); // 字段中文名称
                boolean asContent = compareAnno.asContent(); // 是否用该值当做“字段值”

//                if (asContent) {
//                    Object value = getFieldValue(fieldKey, obj); // 字段值
////                    content = CastUtils.getFormatValue(value, null);
//                    content = (String)getFormattedValue(value, null);
//                }
                Object value = getFieldValue(fieldKey, obj); // 字段值

                if (!objCheckNull(value)) {
                    // 新增结果
                    ComparedResult result = new ComparedResult();
                    result.setFieldName(filedName);
                    result.setOldContent("新增");
//                    result.setNewContent(content);
                    result.setRemark("属性名：" + filedName + "  新值：" + value);
                    comparedResultList.add(result);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        // 新增结果

        /*ComparedResult result = new ComparedResult();
        result.setFieldName(filedName);
        result.setOldContent("新增");
        result.setNewContent(content);
        result.setRemark("新增");
        comparedResultList.add(result);*/

        return comparedResultList;
    }

    /**
     * 删除对比结果
     *
     * @param obj 对象
     * @return 对比结果
     */
    public static List<ComparedResult> deleteComparedResult(Object obj) {
        List<ComparedResult> comparedResultList = new ArrayList<>();
        Class<?> clazz = obj.getClass();

        String filedName = ""; // 字段中文名称
        String content = ""; // 内容

        // 获取class注解
        CompareAnno anon = clazz.getAnnotation(CompareAnno.class);
        if (null != anon) {
            filedName = anon.name();
        }

        // 获取所有字段
        Field[] Fields = clazz.getDeclaredFields();
        for (Field field : Fields) {
            try {

                // 获取注解
                CompareAnno compareAnon = field.getAnnotation(CompareAnno.class);
                // 没有注解，说明不对比字段，跳过
                if (null == compareAnon) {
                    continue;
                }

                String fieldKey = field.getName(); // 字段名
                boolean asContent = compareAnon.asContent(); // 是否用该值当做“字段值”

                if (asContent) {
                    Object value = getFieldValue(fieldKey, obj); // 字段值
//                    content = CastUtils.getFormatValue(value, null);
                    content = (String) getFormattedValue(value, null);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        // 删除结果
        ComparedResult result = new ComparedResult();
        result.setFieldName(filedName);
        result.setOldContent(content);
        result.setNewContent("删除");
        result.setRemark("删除");
        comparedResultList.add(result);

        return comparedResultList;
    }

    /**
     * 获取字段值
     *
     * @param fieldKey 字段名称
     * @param obj      对象
     * @return 字段值
     * @throws Exception 异常
     */
    public static Object getFieldValue(String fieldKey, Object obj) throws Exception {
        PropertyDescriptor pd = new PropertyDescriptor(fieldKey, obj.getClass());
        Method getMethod = pd.getReadMethod();

        // 在obj上调用get方法等同于获得obj的属性值
        return getMethod.invoke(obj);
    }


    public static Object getFormattedValue(Object value, Class<?> targetType) {
        if (targetType == null || value == null) {
            return value;
        }

        if (targetType.isAssignableFrom(value.getClass())) {
            return value;
        }

        if (targetType == String.class) {
            return value.toString();
        } else if (targetType == Integer.class || targetType == int.class) {
            if (value instanceof Number) {
                return ((Number) value).intValue();
            }
            try {
                return Integer.parseInt(value.toString());
            } catch (NumberFormatException e) {
                return null;
            }
        } else if (targetType == Double.class || targetType == double.class) {
            if (value instanceof Number) {
                return ((Number) value).doubleValue();
            }
            try {
                return Double.parseDouble(value.toString());
            } catch (NumberFormatException e) {
                return null;
            }
        } else if (targetType == Boolean.class || targetType == boolean.class) {
            if (value instanceof Boolean) {
                return value;
            }
            return Boolean.parseBoolean(value.toString());
        }

        return null;
    }

    //    public static void main(String[] args) {
//
//        System.out.println(compareValues(null, null));
//        System.out.println(compareValues(2, null));
//        System.out.println(compareValues(null, 2));
//        System.out.println(compareValues(2, 2));
//        System.out.println(compareValues("2", "2"));
//        System.out.println(compareValues(2, "2"));
//
//        System.out.println("------------------------BigDecimal---------------------------");
//
//        System.out.println(compareValues(new BigDecimal("2"), "2"));
//        System.out.println(compareValues(new BigDecimal("2"), new BigDecimal("2.0000")));
//        System.out.println(compareValues(new BigDecimal("2.00"), new BigDecimal("2.0000")));
//        System.out.println(compareValues(new BigDecimal("2.0000"), new BigDecimal("2.0000")));
//        System.out.println(compareValues(new BigDecimal("2.0000"), new BigDecimal("3.0000")));
//
//        System.out.println("------------------------comparedResultList---------------------------");
//
//        OrderDTO oldDTO = new OrderDTO();
//        oldDTO.setId("1");
//        oldDTO.setOrderCode("订单1");
//        oldDTO.setSupplyId("1");
//        oldDTO.setSupplyName("供应商名称1");
//        oldDTO.setOrderAmount(new BigDecimal("111111"));
//        oldDTO.setOrderDate(new Date());
//
//        OrderDTO newDTO = new OrderDTO();
//        newDTO.setId("2");
//        newDTO.setOrderCode("订单2");
//        newDTO.setSupplyId("2");
//        newDTO.setSupplyName("供应商名称2");
//        newDTO.setOrderAmount(new BigDecimal("222222"));
//        newDTO.setOrderDate(DateUtil.getBelowDay(new Date()));
//
//        List<ComparedResult> comparedResultList = compareTwoObject(oldDTO, newDTO);
//        for (ComparedResult comparedResult : comparedResultList) {
//            System.out.println(comparedResult.toString());
//        }
//
//        System.out.println("------------------------comparedResultList2---------------------------");
//
//        OrderDTO orderDTO = new OrderDTO();
//        orderDTO.setId("3");
//        orderDTO.setOrderCode("订单3");
//        orderDTO.setSupplyId("3");
//        orderDTO.setSupplyName("供应商名称3");
//        orderDTO.setOrderAmount(new BigDecimal("333333"));
//        orderDTO.setOrderDate(DateUtil.getBelowDay(new Date()));
//        List<ComparedResult> comparedResultList2 = compareTwoObjectCheckNull(null, orderDTO);
//        for (ComparedResult comparedResult : comparedResultList2) {
//            System.out.println(comparedResult.toString());
//        }
//
//        System.out.println("------------------------comparedResultList3---------------------------");
//
//        List<ComparedResult> comparedResultList3 = compareTwoObjectCheckNull(orderDTO, null);
//        for (ComparedResult comparedResult : comparedResultList3) {
//            System.out.println(comparedResult.toString());
//        }
//
//    }

}
